package resume

import (
	"context"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	v1 "wh-1-backend/api/v1"
	"wh-1-backend/internal/dao"
	"wh-1-backend/internal/model"
	"wh-1-backend/internal/model/do"
	"wh-1-backend/internal/model/entity"
	"wh-1-backend/internal/service"
)

type sResume struct{}

func New() *sResume {
	return &sResume{}
}

func init() {
	service.RegisterResume(New())
}

func (r *sResume) ListByConditionWithPage(ctx context.Context, p model.PageInput, cond model.ResumePageListCondition) (total int, res []*v1.SimpleResumeList, err error) {
	m := dao.Resume.Ctx(ctx)
	if cond.Username != "" {
		m = m.WhereLike(dao.Resume.Columns().Username, cond.Username+"%")
	}
	if cond.Phone != "" {
		m = m.WhereLike(dao.Resume.Columns().Phone, cond.Phone+"%")
	}
	total, err = m.Count()
	if err != nil || total == 0 {
		return
	}
	err = m.Page(p.Page, p.PageSize).Scan(&res)
	if err != nil {
		return
	}
	// ---
	var cityIds []uint
	var functionIds []uint
	var companyIds []uint
	for _, re := range res {
		cityIds = append(cityIds, re.CityId)
		functionIds = append(functionIds, re.FunctionId)
		companyIds = append(companyIds, re.CompanyId)
	}
	cities, err := service.City().ListByIds(ctx, cityIds)
	if err != nil {
		return
	}
	var cityKeyList = make(map[uint]*model.CityList)
	for _, city := range cities {
		cityKeyList[city.Id] = city
	}
	functions, err := service.Function().ListByIds(ctx, functionIds)
	if err != nil {
		return
	}
	var functionKeyList = make(map[uint]*entity.Function)
	for _, fun := range functions {
		functionKeyList[fun.Id] = fun
	}
	companyLists, err := service.Company().ListByIds(ctx, companyIds)
	if err != nil {
		return
	}
	var companyKeyList = make(map[uint]*v1.SimpleCompanyList)
	for _, company := range companyLists {
		companyKeyList[company.Id] = company
	}
	// ---
	for _, re := range res {
		if city, ok := cityKeyList[re.CityId]; ok {
			re.City = city
		}
		if fun, ok := functionKeyList[re.FunctionId]; ok {
			re.Function = fun
		}
		if company, ok := companyKeyList[re.CompanyId]; ok {
			re.Company = company
		}
	}
	return
}

func (r *sResume) Save(ctx context.Context, input model.EditResume1Input) (id uint, err error) {
	lastInsertId, err := dao.Resume.Ctx(ctx).InsertAndGetId(do.Resume{
		Username:              input.Username,
		Birthday:              input.Birthday,
		Gender:                input.Gender,
		Phone:                 input.Phone,
		Qq:                    input.QQ,
		Wx:                    input.Wx,
		Email:                 input.Email,
		CompanyId:             input.CompanyId,
		NationalityId:         input.NationalityId,
		EducationBackgroundId: input.EducationBackgroundId,
		FromId:                input.FromId,
		CityId:                input.CityId,
		IndustryId:            input.IndustryId,
		FunctionId:            input.FunctionId,
		Salary:                input.Salary,
		SelfEvaluation:        input.SelfEvaluation,
	})
	return uint(lastInsertId), err
}

func (r *sResume) SaveAndAttach(ctx context.Context, input model.EditResume1Input) (err error) {
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		id, err2 := r.Save(ctx, input)
		if err2 != nil {
			return err2
		}
		g.Dump(input)
		g.Dump(input.WorkExperience)
		for i := 0; i < len(input.WorkExperience); i++ {
			g.Dump(input.WorkExperience[i])
			input.WorkExperience[i].ResumeId = id
		}
		err2 = service.WorkExp().Insert(ctx, input.WorkExperience)
		if err2 != nil {
			return err2
		}
		for i := 0; i < len(input.ProjectExperience); i++ {
			input.ProjectExperience[i].ResumeId = id
		}
		err2 = service.ProjectExp().Insert(ctx, input.ProjectExperience)
		return err2
	})
	return
}

func (r *sResume) Update(ctx context.Context, id uint, input model.EditResumeInput) (err error) {
	_, err = dao.Resume.Ctx(ctx).Where(dao.Resume.Columns().Id, id).Update(do.Resume{
		Username:              input.Username,
		Birthday:              input.Birthday,
		Gender:                input.Gender,
		Phone:                 input.Phone,
		Qq:                    input.QQ,
		Wx:                    input.Wx,
		Email:                 input.Email,
		CompanyId:             input.CompanyId,
		NationalityId:         input.NationalityId,
		EducationBackgroundId: input.EducationBackgroundId,
		FromId:                input.FromId,
		CityId:                input.CityId,
		IndustryId:            input.IndustryId,
		FunctionId:            input.FunctionId,
		Salary:                input.Salary,
		SelfEvaluation:        input.SelfEvaluation,
	})
	return
}

func (r *sResume) UpdateAndAttach(ctx context.Context, id uint, input model.EditResume1Input) (err error) {
	err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error {
		err2 := r.Update(ctx, id, input.EditResumeInput)
		if err2 != nil {
			return err2
		}
		err2 = service.WorkExp().UpdateByResumeId(ctx, id, input.WorkExperience)
		if err2 != nil {
			return err2
		}
		err2 = service.ProjectExp().UpdateByResumeId(ctx, id, input.ProjectExperience)
		return err2
	})
	return
}

func (r *sResume) getById(ctx context.Context, id uint) (res entity.Resume, err error) {
	err = dao.Resume.Ctx(ctx).Where(dao.Resume.Columns().Id, id).Scan(&res)
	return
}

func (r *sResume) DetailById(ctx context.Context, id uint) (res model.ResumeDetail1, err error) {
	var resume entity.Resume
	resume, err = r.getById(ctx, id)
	if err != nil {
		return
	}
	workExp, err := service.WorkExp().GetByResumeId(ctx, id)
	if err != nil {
		return
	}
	projectExp, err := service.ProjectExp().GetByResumeId(ctx, id)
	res = model.ResumeDetail1{
		ResumeDetail: model.ResumeDetail{
			Id:                    resume.Id,
			Username:              resume.Username,
			Phone:                 resume.Phone,
			Gender:                resume.Gender,
			QQ:                    resume.Qq,
			Wx:                    resume.Wx,
			Email:                 resume.Email,
			CompanyId:             resume.CompanyId,
			NationalityId:         resume.NationalityId,
			EducationBackgroundId: resume.EducationBackgroundId,
			FromId:                resume.FromId,
			FunctionId:            resume.FunctionId,
			IndustryId:            resume.IndustryId,
			CityId:                resume.CityId,
			Salary:                int(resume.Salary),
			Birthday:              resume.Birthday,
			SelfEvaluation:        resume.SelfEvaluation,
			CreatedAt:             resume.CreatedAt,
			UpdatedAt:             resume.UpdatedAt,
		},
		WorkExperience:    workExp,
		ProjectExperience: projectExp,
	}
	return
}

func (r *sResume) Delete(ctx context.Context, ids []uint) (err error) {
	_, err = dao.Resume.Ctx(ctx).WhereIn(dao.Resume.Columns().Id, ids).Delete()
	return
}
